import { StationNetwork } from "GameLoop/Path/StationNetwork";
import { ATeamCombat } from "GameLoop/WorldState/EntityManager/Entitys";
import { PollingStationManager } from "GameLoop/WorldState/PollingStation/PollingStationManager";
import { priority } from "utils/constants/definetypes";

 
/**
 * 房间的基础功能.
 * 1.维持能量的正常运转
 * 2.维持房间爬的正常数量
 */
export default class RoomBaseExtension extends Room 
{
    private idleCreepRecord!:Record<RoleName,Creep[]>
    private  hurtCreep!:Creep[];
    public getWorld(): PollingStationManager
    {
        return global.world
    }
    public lordRoom():Required<Room>
    {
        return Game.rooms[this.getNodeMemory().lord] as Required<Room>;
    }
   
    public getRoleCreeps(role:RoleName):string[]
    {
        if(this.getNodeMemory().roleStatus[role])
        {
            return this.getNodeMemory().roleStatus[role]
        }
        return []
    }

    public registerHurtCreep(creep:Creep)
    {
        if(!this.hurtCreep)
        {
            this.hurtCreep=[creep];
        }
        else
        {
            this.hurtCreep.push(creep);
        }
    }
    public getHurtCreeps()
    {
        if( this.hurtCreep)
        {
            return this.hurtCreep
        }
        return []
    }

   
    
    
    public getIdleCreeps( ):Record<RoleName,Creep[]>
    {
        if(this.idleCreepRecord)
        {
            return this.idleCreepRecord;
        }
        const creepRecord:Record<RoleName,Creep[]>={}as any;
        for(let i=0;i<this.memory.idleCreeps.length;i++)
        {
            const creep = Game.creeps[this.memory.idleCreeps[i]];
            if(!creep)
            {
                this.memory.idleCreeps.splice(i,1);
                continue;
            }
            if( creep.memory.taskid || creep.memory.teamid)
            {
                this.memory.idleCreeps.splice(i,1);
                continue;
            }
            if(creepRecord[creep.memory.Role])
            {
                creepRecord[creep.memory.Role].push(creep);
            }
            else
            {
                creepRecord[creep.memory.Role]=[creep];
            }
        }
        this.idleCreepRecord = creepRecord;
        return this.idleCreepRecord;
    }
    public removeIdleCreep(creep:Creep)
    {
        const idx = this.memory.idleCreeps.indexOf(creep.name);
        if(idx>-1)
        {
            this.memory.idleCreeps.splice(idx,1);
        }
        // 从this.idleCreepRecord 中移除

        const ret = this.idleCreepRecord[creep.ActiveRole()];
        if(ret)
        {
            const idx =  _.findIndex(ret,e=>e.name == creep.name);
            if(idx>-1)
            {
                ret.splice(idx,1);
            }
        }
    }

    public addCreep(creepName:string,role:RoleName)
    {
       
        this.getNodeMemory().idleCreeps.push(creepName);
        if(this.getNodeMemory().roleStatus[role])
        {
            this.getNodeMemory().roleStatus[role].push(creepName);
        }
        else
        {
            this.getNodeMemory().roleStatus[role]=[creepName];
        }
        Game.creeps[creepName].memory.state=undefined
    }

    public freeTaskCreeps<T extends ITaskDeclare["creep"]|ITaskDeclare["team"]>(task:T,curcreeps?:Creep[])
    {
        let creeps:Creep[] = [];
        if(curcreeps)
        {
            
            creeps=curcreeps;
            
        }
        else 
        {
            creeps=task.data.creeps?task.data.creeps.map(e=>Game.creeps[e]):[];
        }
        
        if(task.type =="creep")
        {
            creeps.forEach(e=>
                {
                    if(!e)
                    {
                        return;
                    }
                    e.memory.taskid=undefined;
                    let idx = task.data.creeps.findIndex(n=>n== e.name);
                    if(idx>-1)
                    {
                        task.data.creeps.splice(idx,1);
                    }
                    this.getNodeMemory().idleCreeps.push(e.name);
                    
                })
        }
        else if(task.type =="team")
        {
            creeps.forEach(e=>
            {
                if(!e)
                {
                    return;
                }
                e.memory.taskid=undefined;
                let idx = task.data.creeps.findIndex(n=>n== e.name);
                    if(idx>-1)
                    {
                        task.data.creeps.splice(idx,1);
                    }
                    this.getNodeMemory().idleCreeps.push(e.name);
                
            })
            for(let k in task.data.teams)
            {
                for(const e of task.data.teams[k as EntityType])
                {
                    const team = this.getEntityByID(e) as ATeamCombat;
                    team.getNodeMemory().bindTask = undefined as any;
                }
                
            }
        }
    }

    public getIdlePowerCreeps( ):PowerCreep[]
    {
        const idlePc:PowerCreep[]=[];
        
        for(const e of  this.memory.powerCreeps)
        {
            const pc = Game.powerCreeps[e];
            if(pc && pc.memory.OwnerRoom ==this.name && pc.ticksToLive)
            {
                if(!pc.memory.taskid || !this.findTaskById(pc.memory.taskid,"pc"))
                {
                    idlePc.push(pc);
                    pc.memory.taskid=undefined;
                }
            }
            else
            {
                // pc已经不存在,已经不处于本房间的绑定
            }
        }
        return idlePc;
    }
    /**
     * 添加任务 id相同则返回false 不同则新增成功
     * @param task 
     * @param type 
     * @returns 
     */
    public addNewTask<T extends ITask>(task:T):boolean
    {
        const ret = (global.GameLoop as any).decision.addNewTask(this.name,this.getNodeMemory(),task ); 
        // if(ret)
        // {
        //     this.log("info","新增任务",task.type,JSON.stringify(task));
        // }
        return ret;
    }


    public findTaskById<T extends ITask>(id:string,type?:TaskType):T|undefined
    {
        const memory = this.getNodeMemory();
     
        if(type)
        {
            if(! memory.Tasks ||  !memory.Tasks[type])
            {
                return undefined;
            }
            for(const e of memory.Tasks[type])
            {
                if(e.id == id)
                {
                    return e as any;
                }
            }
        }
        else
        {
            for(let k in memory.Tasks)
            {
                for(const e of memory.Tasks[k as TaskType])
                {
                    if(e.id == id)
                    {
                        return e as any;
                    }
                }
            }
        }
        return undefined
    }
    public getTaskById<T extends ITask>(id:string,typeRange:TaskType[]):T|undefined
    {
        const memory = this.getNodeMemory();
        if(memory.Tasks)
        {
            for(const e of typeRange)
            {
                if(!memory.Tasks[e])
                {
                    continue;
                }
                const item = memory.Tasks[e].find(i=>i.id == id);
                if(item)
                {
                    return item as any;
                }
            }
        }
        return undefined
    }
    public deleteTaskById<T extends TaskType>(id:string|ITaskFilter<T>,type?:TaskType):ITaskDeclare[T]|undefined
    {
        const memory = this.getNodeMemory();
        let filter:ITaskFilter<T>
        if(typeof id == "string")
        {
            filter=(e:ITaskDeclare[T])=>
            {
                return e.id == id
            }
        }
        else
        {
            filter = id;
        }
        const deleteTask=(filter:ITaskFilter<T>,tasks:ITaskDeclare[T][],type:TaskType)=>
        {
            if(!tasks)
            {
                return undefined
            }
            let idx =  tasks.findIndex(e=>filter(e));
            if(idx>-1)
            {
                this.log('info',`[${type}->任务分类]`,"删除任务",tasks[idx].type,JSON.stringify(tasks[idx].id))
                this.freeTaskCreeps(tasks[idx] as any);
                return tasks.splice(idx,1)[0];
            }
            
            return undefined
        }
        if(type)
        {
          
            return deleteTask(filter,memory.Tasks[type] as  ITaskDeclare[T][],type) as ITaskDeclare[T];
        }
        else
        {
            for(let k in memory.Tasks)
            {
                const ret =  deleteTask(filter,memory.Tasks[k as TaskType]  as  ITaskDeclare[T][],k as TaskType) as ITaskDeclare[T] ;
                if(ret )
                {
                    // if(memory.Tasks[k as TaskType].length ==0)
                    // {
                    //     delete memory.Tasks[k as TaskType];
                    // }
                    return ret;
                }
            }
        }
        return undefined
    }
    /**
     * 尝试推迟任务,如果推迟成功返回true 推迟失败则直接删除任务
     * @param id 
     * @param type 
     * @returns 
     */
    public tryDelayTaskById<T extends TaskType>(id:string,type?:T): boolean
    {
        const task = this.deleteTaskById(id,type);
        if(task)
        {
            const memory = this.getNodeMemory();
            task.priority =priority.F;
            if((task as any).delay)
            {
                (task as any).delay++;
            }
            else 
            {
                (task as any).delay=1
            }
            
            if(memory.Tasks[task.type] && memory.Tasks[task.type] .length>1)
            {
                memory.Tasks[task.type].push(task);
                return true;
            }
            return false;
        }
        return false;
    }
    public getTaskByType<T extends TaskType>(type:T,filter?:(task:ITaskDeclare[T])=>boolean):ITaskDeclare[T][]
    {
        
        const memory = this.getNodeMemory();
        if(!memory.Tasks[type])
        {
            return []
            // memory.Tasks[type]=[];
        }
        if(filter)
        {
           return  (memory.Tasks[type] as ITaskDeclare[T][]).filter(filter)
        }
        else
        {
            return  memory.Tasks[type] as ITaskDeclare[T][]
        }
    }
    public pauseTask<T extends ITaskDeclare["creep"]|ITaskDeclare["team"]>(task:T,pause:number):void
    {
        task.pause = pause;
        const spawn = this.getEntity("SpawnEntity");
        if(task.type =="creep")
        {
            task.data.creeps.forEach(e=>
                {
                    if(Game.creeps[e])
                    {
                        Game.creeps[e].memory.taskid=undefined;
                        this.getNodeMemory().idleCreeps.push(e);
                        // this.addCreep(e, Game.creeps[e].ActiveRole())
                    };
                })
                
            task.data.creeps=[];
           
        }
        else if(task.type =="team")
        {
            task.data.creeps.forEach(e=>
                {
                    if(Game.creeps[e])
                    {
                        Game.creeps[e].memory.taskid=undefined;
                        this.getNodeMemory().idleCreeps.push(e);
                        // this.addCreep(e, Game.creeps[e].ActiveRole())
                    };
                })
                
            task.data.creeps=[];
            const _this = this;
            const team = _.flatten(Object.values((task as ITaskDeclare["team"]).data.teams)).map(e=>_this.getEntityByID(e));
            team.forEach(e=> 
                {
                    if(e)
                    {
                        spawn.deleteTasksByOwner(e.GUID())
                    }});
            (task as ITaskDeclare["team"]).data.teams={} as any;
        }
        spawn.deleteTasksByOwner(task.id);
    }

    public canExecute(tick:number):boolean
    {
        const seqId = this.memory.seqId || 5
        return (Game.time - seqId) % tick === 0
    }


    public addTimer<T extends TimerArg<TEventTypes>>(event:T,ttl:number,interval=1)
    {
        return (global.GameLoop as any).worldstate.Timer.register(event,ttl,interval);
    }

    public registerExcessResource( resource: ResourceConstant, amount: number): void
    {
        global.resourceStats.registerExcessResource(this,resource,amount)
    }
    public registerShortageResource(resource: ResourceConstant, amount: number): void 
    {
        global.resourceStats.registerShortageResource(this,resource,amount)
    }
    public registerNotify(region:EventRegion,eventtype:INotifyEvent)
    {
        (global.GameLoop as any).worldstate.registerNotify(region,eventtype);
    }

    public deleteRemoteMine(mineRoom:string)
    {
        let entitys =this.getEntitys("OutMineEntity");
        const entitys2 =this.getEntitys("OutMinerialEntity");
        entitys = entitys.concat(entitys2 as any );
        const deleteIDs :string[]= []
        for(const e of entitys)
        {
            if(e.roomName == mineRoom)
            {
                global.entityDB.removeEntityByID(e.GUID());
                deleteIDs.push(e.GUID());
            }
        }
        const _this = this;
        if(mineRoom != this.name && Game.rooms[mineRoom].getType()!=1)
        {
            this.getTaskByType("creep",e=>e.data.room == mineRoom).forEach(e=>
                {
                    _this.deleteTaskById(e.id,'creep');
                })
                
                {
                    Memory.rooms[mineRoom]={} as any;
                }
        }
        else 
        {
            deleteIDs.forEach(e=>
                {
                    _this.deleteTaskById(e,'creep');
                })
        }

        
    }
}
